aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/NaCl/ExpandStructRegs.cpp36
-rw-r--r--test/Transforms/NaCl/expand-struct-regs.ll11
2 files changed, 47 insertions, 0 deletions
diff --git a/lib/Transforms/NaCl/ExpandStructRegs.cpp b/lib/Transforms/NaCl/ExpandStructRegs.cpp
index ac83d33e78..5c11a76c8b 100644
--- a/lib/Transforms/NaCl/ExpandStructRegs.cpp
+++ b/lib/Transforms/NaCl/ExpandStructRegs.cpp
@@ -97,6 +97,37 @@ static void SplitUpPHINode(PHINode *Phi) {
Phi->eraseFromParent();
}
+static void SplitUpSelect(SelectInst *Select) {
+ StructType *STy = cast<StructType>(Select->getType());
+ Value *NewStruct = UndefValue::get(STy);
+
+ // Create a separate SelectInst for each struct field.
+ for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) {
+ SmallVector<unsigned, 1> EVIndexes;
+ EVIndexes.push_back(Index);
+
+ Value *TrueVal = CopyDebug(
+ ExtractValueInst::Create(Select->getTrueValue(), EVIndexes,
+ Select->getName() + ".extract", Select),
+ Select);
+ Value *FalseVal = CopyDebug(
+ ExtractValueInst::Create(Select->getFalseValue(), EVIndexes,
+ Select->getName() + ".extract", Select),
+ Select);
+ Value *NewSelect = CopyDebug(
+ SelectInst::Create(Select->getCondition(), TrueVal, FalseVal,
+ Select->getName() + ".index", Select), Select);
+
+ // Reconstruct the original struct value.
+ NewStruct = CopyDebug(
+ InsertValueInst::Create(NewStruct, NewSelect, EVIndexes,
+ Select->getName() + ".insert", Select),
+ Select);
+ }
+ Select->replaceAllUsesWith(NewStruct);
+ Select->eraseFromParent();
+}
+
template <class InstType>
static void ProcessLoadOrStoreAttrs(InstType *Dest, InstType *Src) {
CopyDebug(Dest, Src);
@@ -215,6 +246,11 @@ bool ExpandStructRegs::runOnFunction(Function &Func) {
SplitUpPHINode(Phi);
Changed = true;
}
+ } else if (SelectInst *Select = dyn_cast<SelectInst>(Inst)) {
+ if (Select->getType()->isStructTy()) {
+ SplitUpSelect(Select);
+ Changed = true;
+ }
}
}
}
diff --git a/test/Transforms/NaCl/expand-struct-regs.ll b/test/Transforms/NaCl/expand-struct-regs.ll
index 8291ec5069..0cc2c6db85 100644
--- a/test/Transforms/NaCl/expand-struct-regs.ll
+++ b/test/Transforms/NaCl/expand-struct-regs.ll
@@ -92,6 +92,17 @@ bb:
; CHECK-NEXT: %phi.index{{.*}} = phi i32 [ %val.field{{.*}}, %entry ], [ %val.field{{.*}}, %entry ]
+define void @struct_select_inst(i1 %cond, %struct* %ptr1, %struct* %ptr2) {
+ %val1 = load %struct* %ptr1
+ %val2 = load %struct* %ptr2
+ %select = select i1 %cond, %struct %val1, %struct %val2
+ ret void
+}
+; CHECK: define void @struct_select_inst
+; CHECK: %select.index{{.*}} = select i1 %cond, i8 %val1.field{{.*}}, i8 %val2.field{{.*}}
+; CHECK-NEXT: %select.index{{.*}} = select i1 %cond, i32 %val1.field{{.*}}, i32 %val2.field{{.*}}
+
+
define void @insert_and_extract(i8* %out0, i32* %out1) {
%temp = insertvalue %struct undef, i8 100, 0
%sval = insertvalue %struct %temp, i32 200, 1