llvm.org GIT mirror llvm / 4815d56
ARM isel bug fix for adds/subs operands. Modified ARMISelLowering::AdjustInstrPostInstrSelection to handle the full gamut of CPSR defs/uses including instructins whose "optional" cc_out operand is not really optional. This allowed removal of the hasPostISelHook to simplify the .td files and make the implementation more robust. Fixes rdar://10137436: sqlite3 miscompile git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140134 91177308-0d34-0410-b5e6-96231b3b80d8 Andrew Trick 8 years ago
10 changed file(s) with 122 addition(s) and 46 deletion(s). Raw diff Collapse all Expand all
476476 return Flags & (1 << MCID::UsesCustomInserter);
477477 }
478478
479 /// hasPostISelHook - Return true if this instruction requires *adjustment*
480 /// after instruction selection by calling a target hook. For example, this
481 /// can be used to fill in ARM 's' optional operand depending on whether
482 /// the conditional flag register is used.
483 bool hasPostISelHook() const {
484 return Flags & (1 << MCID::HasPostISelHook);
485 }
486
487479 /// isRematerializable - Returns true if this instruction is a candidate for
488480 /// remat. This flag is deprecated, please don't use it anymore. If this
489481 /// flag is set, the isReallyTriviallyReMaterializable() method is called to
762762 }
763763
764764 // Run post-isel target hook to adjust this instruction if needed.
765 if (II.hasPostISelHook())
766 TLI->AdjustInstrPostInstrSelection(MI, Node);
765 TLI->AdjustInstrPostInstrSelection(MI, Node);
767766 }
768767
769768 /// EmitSpecialNode - Generate machine code for a target-independent node and
178178
179179 void TargetLowering::AdjustInstrPostInstrSelection(MachineInstr *MI,
180180 SDNode *Node) const {
181 #ifndef NDEBUG
182 dbgs() << "If a target marks an instruction with "
183 "'hasPostISelHook', it must implement "
184 "TargetLowering::AdjustInstrPostInstrSelection!";
185 #endif
186 llvm_unreachable(0);
181 // Do nothing unless the target overrides it.
187182 }
188183
189184 //===----------------------------------------------------------------------===//
57515751 }
57525752 }
57535753
5754 /// Generally, ARM instructions may be optionally encoded with a 's'
5755 /// bit. However, some opcodes have a compact encoding that forces an implicit
5756 /// 's' bit. List these exceptions here.
5757 static bool hasForcedCPSRDef(const MCInstrDesc &MCID) {
5758 switch (MCID.getOpcode()) {
5759 case ARM::t2ADDSri:
5760 case ARM::t2ADDSrr:
5761 case ARM::t2ADDSrs:
5762 case ARM::t2SUBSri:
5763 case ARM::t2SUBSrr:
5764 case ARM::t2SUBSrs:
5765 return true;
5766 }
5767 return false;
5768 }
5769
57545770 void ARMTargetLowering::AdjustInstrPostInstrSelection(MachineInstr *MI,
57555771 SDNode *Node) const {
5756 // Adjust potentially 's' setting instructions after isel, i.e. ADC, SBC,
5757 // RSB, RSC. Coming out of isel, they have an implicit CPSR def, but the
5758 // optional operand is not filled in. If the carry bit is used, then change
5759 // the optional operand to CPSR. Otherwise, remove the CPSR implicit def.
5772 // Adjust potentially 's' setting instructions after isel, i.e. ADC, SBC, RSB,
5773 // RSC. Coming out of isel, they have an implicit CPSR def, but the optional
5774 // operand is still set to noreg. If needed, set the optional operand's
5775 // register to CPSR, and remove the redundant implicit def.
5776
57605777 const MCInstrDesc &MCID = MI->getDesc();
5761 if (Node->hasAnyUseOfValue(1)) {
5762 MachineOperand &MO = MI->getOperand(MCID.getNumOperands() - 1);
5763 MO.setReg(ARM::CPSR);
5764 MO.setIsDef(true);
5765 } else {
5766 for (unsigned i = MCID.getNumOperands(), e = MI->getNumOperands();
5767 i != e; ++i) {
5768 const MachineOperand &MO = MI->getOperand(i);
5769 if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR) {
5770 MI->RemoveOperand(i);
5771 break;
5772 }
5773 }
5774 }
5778 unsigned ccOutIdx = MCID.getNumOperands() - 1;
5779 bool forcedCPSR = hasForcedCPSRDef(MCID);
5780
5781 // Any ARM instruction that sets the 's' bit should specify an optional
5782 // "cc_out" operand in the last operand position.
5783 if (!MCID.hasOptionalDef() || !MCID.OpInfo[ccOutIdx].isOptionalDef()) {
5784 assert(!forcedCPSR && "Optional cc_out operand required");
5785 return;
5786 }
5787 // Look for an implicit def of CPSR added by MachineInstr ctor.
5788 bool definesCPSR = false;
5789 bool deadCPSR = false;
5790 for (unsigned i = MCID.getNumOperands(), e = MI->getNumOperands();
5791 i != e; ++i) {
5792 const MachineOperand &MO = MI->getOperand(i);
5793 if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR) {
5794 definesCPSR = true;
5795 if (MO.isDead())
5796 deadCPSR = true;
5797 MI->RemoveOperand(i);
5798 break;
5799 }
5800 }
5801 if (!definesCPSR) {
5802 assert(!forcedCPSR && "Optional cc_out operand required");
5803 return;
5804 }
5805 assert(deadCPSR == !Node->hasAnyUseOfValue(1) && "inconsistent dead flag");
5806
5807 // If possible, select the encoding that does not set the 's' bit.
5808 if (deadCPSR && !forcedCPSR)
5809 return;
5810
5811 MachineOperand &MO = MI->getOperand(ccOutIdx);
5812 MO.setReg(ARM::CPSR);
5813 MO.setIsDef(true);
5814 if (deadCPSR)
5815 MO.setIsDead();
57755816 }
57765817
57775818 //===----------------------------------------------------------------------===//
10251025 }
10261026
10271027 /// AsI1_rbin_s_is - Same as AsI1_rbin_s_is except it sets 's' bit by default.
1028 let hasPostISelHook = 1, isCodeGenOnly = 1, Defs = [CPSR] in {
1028 let isCodeGenOnly = 1, Defs = [CPSR] in {
10291029 multiclass AsI1_rbin_s_is opcod, string opc,
10301030 InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
10311031 PatFrag opnode, bit Commutable = 0> {
10891089 }
10901090
10911091 /// AsI1_bin_s_irs - Same as AsI1_bin_irs except it sets the 's' bit by default.
1092 let hasPostISelHook = 1, isCodeGenOnly = 1, Defs = [CPSR] in {
1092 let isCodeGenOnly = 1, Defs = [CPSR] in {
10931093 multiclass AsI1_bin_s_irs opcod, string opc,
10941094 InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
10951095 PatFrag opnode, bit Commutable = 0> {
12771277 /// AI1_adde_sube_irs - Define instructions and patterns for adde and sube.
12781278 multiclass AI1_adde_sube_irs opcod, string opc, PatFrag opnode,
12791279 string baseOpc, bit Commutable = 0> {
1280 let hasPostISelHook = 1, Defs = [CPSR], Uses = [CPSR] in {
1280 let Defs = [CPSR], Uses = [CPSR] in {
12811281 def ri : AsI1
12821282 DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
12831283 [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_imm:$imm, CPSR))]>,
13651365 /// AI1_rsc_irs - Define instructions and patterns for rsc
13661366 multiclass AI1_rsc_irs opcod, string opc, PatFrag opnode,
13671367 string baseOpc> {
1368 let hasPostISelHook = 1, Defs = [CPSR], Uses = [CPSR] in {
1368 let Defs = [CPSR], Uses = [CPSR] in {
13691369 def ri : AsI1
13701370 DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
13711371 [(set GPR:$Rd, CPSR, (opnode so_imm:$imm, GPR:$Rn, CPSR))]>,
591591
592592 /// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the
593593 /// instruction modifies the CPSR register.
594 let hasPostISelHook = 1, isCodeGenOnly = 1, Defs = [CPSR] in {
594 let isCodeGenOnly = 1, Defs = [CPSR] in {
595595 multiclass T2I_bin_s_irs opcod, string opc,
596596 InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
597597 PatFrag opnode, bit Commutable = 0> {
737737
738738 /// T2I_rbin_s_is - Same as T2I_rbin_irs except sets 's' bit and the register
739739 /// version is not needed since this is only for codegen.
740 let hasPostISelHook = 1, isCodeGenOnly = 1, Defs = [CPSR] in {
740 let isCodeGenOnly = 1, Defs = [CPSR] in {
741741 multiclass T2I_rbin_s_is opcod, string opc, PatFrag opnode> {
742742 // shifted imm
743743 def ri : T2sTwoRegImm<
18451845 IIC_iALUi, IIC_iALUr, IIC_iALUsi,
18461846 BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>;
18471847
1848 let hasPostISelHook = 1 in {
18491848 defm t2ADC : T2I_adde_sube_irs<0b1010, "adc",
18501849 BinOpWithFlagFrag<(ARMadde node:$LHS, node:$RHS, node:$FLAG)>, 1>;
18511850 defm t2SBC : T2I_adde_sube_irs<0b1011, "sbc",
18521851 BinOpWithFlagFrag<(ARMsube node:$LHS, node:$RHS, node:$FLAG)>>;
1853 }
18541852
18551853 // RSB
18561854 defm t2RSB : T2I_rbin_irs <0b1110, "rsb",
0 ; RUN: llc -march=thumb -mcpu=cortex-a8 < %s
1 ; rdar://problem/10137436: sqlite3 miscompile
2 ;
3 ; CHECK: subs
4 ; CHECK: cmp
5 ; CHECK: it
6
7 target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32"
8 target triple = "thumbv7-apple-ios4.0.0"
9
10 declare i8* @__memset_chk(i8*, i32, i32, i32) nounwind
11
12 define hidden fastcc i32 @sqlite3VdbeExec(i32* %p) nounwind {
13 entry:
14 br label %sqlite3VarintLen.exit7424
15
16 sqlite3VarintLen.exit7424: ; preds = %do.body.i7423
17 br label %do.body.i
18
19 do.body.i: ; preds = %do.body.i, %sqlite3VarintLen.exit7424
20 br i1 undef, label %do.body.i, label %sqlite3VarintLen.exit
21
22 sqlite3VarintLen.exit: ; preds = %do.body.i
23 %sub2322 = add i64 undef, undef
24 br i1 undef, label %too_big, label %if.end2327
25
26 if.end2327: ; preds = %sqlite3VarintLen.exit
27 br i1 undef, label %if.end2341, label %no_mem
28
29 if.end2341: ; preds = %if.end2327
30 br label %for.body2355
31
32 for.body2355: ; preds = %for.body2355, %if.end2341
33 %add2366 = add nsw i32 undef, undef
34 br i1 undef, label %for.body2377, label %for.body2355
35
36 for.body2377: ; preds = %for.body2355
37 %conv23836154 = zext i32 %add2366 to i64
38 %sub2384 = sub i64 %sub2322, %conv23836154
39 %conv2385 = trunc i64 %sub2384 to i32
40 %len.0.i = select i1 undef, i32 %conv2385, i32 undef
41 %sub.i7384 = sub nsw i32 %len.0.i, 0
42 %call.i.i7385 = call i8* @__memset_chk(i8* undef, i32 0, i32 %sub.i7384, i32 undef) nounwind
43 unreachable
44
45 too_big: ; preds = %sqlite3VarintLen.exit
46 unreachable
47
48 no_mem: ; preds = %if.end2327, %for.body, %entry.no_mem_crit_edge
49 unreachable
50
51 sqlite3ErrStr.exit: ; preds = %if.then82
52 unreachable
53 }
308308 isReMaterializable = R->getValueAsBit("isReMaterializable");
309309 hasDelaySlot = R->getValueAsBit("hasDelaySlot");
310310 usesCustomInserter = R->getValueAsBit("usesCustomInserter");
311 hasPostISelHook = R->getValueAsBit("hasPostISelHook");
312311 hasCtrlDep = R->getValueAsBit("hasCtrlDep");
313312 isNotDuplicable = R->getValueAsBit("isNotDuplicable");
314313 hasSideEffects = R->getValueAsBit("hasSideEffects");
232232 bool isReMaterializable;
233233 bool hasDelaySlot;
234234 bool usesCustomInserter;
235 bool hasPostISelHook;
236235 bool hasCtrlDep;
237236 bool isNotDuplicable;
238237 bool hasSideEffects;
287287 if (Inst.isNotDuplicable) OS << "|(1<
288288 if (Inst.Operands.hasOptionalDef) OS << "|(1<
289289 if (Inst.usesCustomInserter) OS << "|(1<
290 if (Inst.hasPostISelHook) OS << "|(1<
291290 if (Inst.Operands.isVariadic)OS << "|(1<
292291 if (Inst.hasSideEffects) OS << "|(1<
293292 if (Inst.isAsCheapAsAMove) OS << "|(1<
344343
345344 // We must emit the PHI opcode first...
346345 std::string Namespace = Target.getInstNamespace();
347
346
348347 if (Namespace.empty()) {
349348 fprintf(stderr, "No instructions defined!\n");
350349 exit(1);